added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / for.cs
blob0238be8b12391bf8e77bbbe39c321bb2da85d273
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
18 using System;
19 using System.Collections;
20 using System.Reflection;
21 using System.Reflection.Emit;
23 internal sealed class For : AST{
24 private AST initializer;
25 private AST condition;
26 private AST incrementer;
27 private AST body;
28 private Completion completion;
30 internal For(Context context, AST initializer, AST condition, AST incrementer, AST body)
31 : base(context) {
32 this.initializer = initializer;
33 this.condition = condition;
34 this.incrementer = incrementer;
35 this.body = body;
36 this.completion = new Completion();
39 // no debug info for the for statement iteself
40 internal override Object Evaluate(){
41 this.completion.Continue = 0;
42 this.completion.Exit = 0;
43 this.completion.value = null;
44 this.initializer.Evaluate();
45 while (Convert.ToBoolean(this.condition.Evaluate()) == true){
46 Completion c = (Completion)this.body.Evaluate();
47 if (c.value != null)
48 this.completion.value = c.value;
49 if (c.Continue > 1){
50 this.completion.Continue = c.Continue - 1;
51 break;
53 if (c.Exit > 0){
54 this.completion.Exit = c.Exit - 1;
55 break;
57 if (c.Return)
58 return c;
59 this.incrementer.Evaluate();
61 return this.completion;
64 internal override AST PartiallyEvaluate(){
65 this.initializer = this.initializer.PartiallyEvaluate();
66 ScriptObject current_scope = Globals.ScopeStack.Peek();
67 while (current_scope is WithObject) current_scope = current_scope.GetParent();
68 if (current_scope is FunctionScope){
69 FunctionScope scope = (FunctionScope)current_scope;
70 BitArray before = scope.DefinedFlags;
71 this.condition = this.condition.PartiallyEvaluate();
72 //Do not need to clear the defined flags because the condition is always completely executed if the body is reached.
73 this.body = this.body.PartiallyEvaluate();
74 scope.DefinedFlags = before;
75 this.incrementer = this.incrementer.PartiallyEvaluate();
76 scope.DefinedFlags = before;
77 }else{
78 this.condition = this.condition.PartiallyEvaluate();
79 this.body = this.body.PartiallyEvaluate();
80 this.incrementer = this.incrementer.PartiallyEvaluate();
82 IReflect conditiontype = this.condition.InferType(null);
83 if (conditiontype is FunctionPrototype || conditiontype == Typeob.ScriptFunction)
84 this.context.HandleError(JSError.SuspectLoopCondition);
85 return this;
88 internal override void TranslateToIL(ILGenerator il, Type rtype){
89 //This assumes that rtype == Void.class
90 Label body_start = il.DefineLabel();
91 Label continue_lab = il.DefineLabel();
92 Label first_time = il.DefineLabel();
93 Label loop_end = il.DefineLabel();
94 bool noCondition = false;
95 compilerGlobals.BreakLabelStack.Push(loop_end);
96 compilerGlobals.ContinueLabelStack.Push(continue_lab);
97 if (!(this.initializer is EmptyLiteral)){
98 this.initializer.context.EmitLineInfo(il);
99 this.initializer.TranslateToIL(il, Typeob.Void);
101 il.MarkLabel(body_start);
102 if (!(this.condition is ConstantWrapper) || !(this.condition.Evaluate() is bool) || !((bool)this.condition.Evaluate())){
103 this.condition.context.EmitLineInfo(il);
104 this.condition.TranslateToConditionalBranch(il, false, loop_end, false);
105 }else
106 if (this.condition.context.StartPosition + 1 == this.condition.context.EndPosition)
107 // the for does not have a condition specified. If there is no increment as well emit debug info for the whole for
108 noCondition = true;
109 this.body.TranslateToIL(il, Typeob.Void);
110 il.MarkLabel(continue_lab);
111 if (!(this.incrementer is EmptyLiteral)){
112 this.incrementer.context.EmitLineInfo(il);
113 this.incrementer.TranslateToIL(il, Typeob.Void);
114 }else if (noCondition){
115 this.context.EmitLineInfo(il);
117 il.Emit(OpCodes.Br, body_start);
118 il.MarkLabel(loop_end);
119 compilerGlobals.BreakLabelStack.Pop();
120 compilerGlobals.ContinueLabelStack.Pop();
123 internal override void TranslateToILInitializer(ILGenerator il){
124 this.initializer.TranslateToILInitializer(il);
125 this.condition.TranslateToILInitializer(il);
126 this.incrementer.TranslateToILInitializer(il);
127 this.body.TranslateToILInitializer(il);